package com.example.my_self_view.viewdrag

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.core.view.ViewCompat
import androidx.customview.widget.ViewDragHelper

// 按住ListView拖拽，此时触摸事件还是传给ListView，当这个触摸事件没有UP或者cancel时，是不会转移别的view的，
// 所以当滑到ListView的顶部时，需要松手再刷一下，才能
class VerticalDragListView: FrameLayout {

    // 可以认为这是系统给我们写好的一个工具类
    private lateinit var mDragHelper: ViewDragHelper
    private lateinit var mDragListView: View
    private var mMenuHeight = 0
    constructor(context: Context): this(context, null)
    constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): this(context, attrs, defStyleAttr, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int): super(context, attrs, defStyleAttr, defStyleRes) {
        mDragHelper = ViewDragHelper.create(this, mDragHelperCallback)
    }

    override fun onFinishInflate() {
        super.onFinishInflate() // 在setContentView完成之后，才会调用这个方法，调用完这个方法才会调用view的绘制流程，所以拿到宽高

        val childCount = childCount
        if (childCount != 2) {
            throw RuntimeException("VerticalDragListView 只能包含两个子布局")
        }

        mDragListView = getChildAt(1)

//        val menuView = getChildAt(0)
//        mMenuHeight = menuView.measuredHeight
    }

//    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (changed) {
            val menuView = getChildAt(0)
            mMenuHeight = menuView.measuredHeight
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        mDragHelper.processTouchEvent(event)
        return true
    }

    // 1.拖动我们的子view
    private val mDragHelperCallback = object : ViewDragHelper.Callback(){
        override fun tryCaptureView(child: View, pointerId: Int): Boolean {
            // 指定该子View是否可以拖动
            // 只能是列表可以拖动
            // 后面的view不能动
            return mDragListView == child // 返回true就是可以拖动
        }

        override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
            // 垂直拖动移动的位置
            // 垂直拖动的范围只能是后面菜单 View 的高度
            var finalTop = top

            if (top <= 0) {
                finalTop = 0
            }

            if (top >= mMenuHeight) {
                finalTop = mMenuHeight
            }

            return finalTop
        }

//        override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
//            // 水平拖动移动的位置
//            return left
//        }

        override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
            // 手指松开的时候两者选其一，要么打开要么关闭
            if (mDragListView.top > mMenuHeight / 2) {
                // 滚动到菜单的高度(打开)
                mDragHelper.settleCapturedViewAt(0, mMenuHeight)
                mMenuIsOpen = true
            } else {
                // 滚动到0的位置(关闭)
                mDragHelper.settleCapturedViewAt(0,0)
                mMenuIsOpen = false
            }

            invalidate()
        }
    }

    // 现象就是ListView可以滑动，但是菜单滑动没有效果了
    private var mDown = 0f
    // 菜单是否打开
    private var mMenuIsOpen = false

    // because ACTION_DOWN was not received for this pointer before ACTION_MOVE.
    // VDLV.onInterceptTouchEvent() -> LV.onTouch() -> VDLV.onInterceptTouchEvent().MOVE -> VDLV.onTouchEvent().MOVE
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        // 菜单打开要全部拦截
        if (mMenuIsOpen) {
            return true
        }
        // 向下滑动拦截，不要给ListView做处理，但是ListView使用了 requestDisallowInterceptTouchEvent(true) 方法
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                mDown = ev.y
                // 让 DragHelper 拿一个完整的事件
                mDragHelper.processTouchEvent(ev)
            }
            MotionEvent.ACTION_MOVE -> {
                val moveY = ev.y
                if (moveY - mDown > 0f && !canChildScrollUp()) {
                    // 向下滑动 并且 滚动到了顶部，拦截不让ListView做处理
                    return true
                }
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    /**
     * 还能否向上滚
     */
    private fun canChildScrollUp(): Boolean {
        return ViewCompat.canScrollVertically(mDragListView, -1)
    }

    /**
     * 响应滚动
     */
    override fun computeScroll() {
        if (mDragHelper.continueSettling(true)) {
            invalidate()
        }
    }
}